package com.learn.training.multithread.chapter6.minchapter7.demo1;

import java.util.concurrent.locks.StampedLock;

public class Point {

    private final StampedLock stampedLock = new StampedLock();

    private double x;
    private double y;

    public void write(double deltaX, double deltaY){
        long stamp = stampedLock.writeLock();//获取写锁
        try {
            x += deltaX;
            y += deltaY;
        }finally {
            System.out.println(Thread.currentThread().getName() + "  write end x : " + x + "  y:  " + y);
            stampedLock.unlockWrite(stamp);//释放写锁
        }
    }

    public double distanceFromOrigin(){
        // 获取一个乐观读锁
        long stamp = stampedLock.tryOptimisticRead();

        //下面两行代码不是原子操作
        //假设x,y = (100,200)
        double currentX = x;
        //此处已读取到x=100,但x,y可能被写线程修改为(300,400)
        double currentY = y;
        //此处已读取到y，如果没有写入，读取是正确的(100,200)，如果有写入，读取是错误的(100,400)

        System.out.println(Thread.currentThread().getName() + " first  read x : " + currentX + "  y : " + currentY);

        if (stampedLock.validate(stamp)) {//检查乐观读锁后是否有其他写锁发生
            stamp = stampedLock.readLock();//获取一个悲观读锁
            try {
                currentX = x;
                currentY = y;
            }finally {
                System.out.println(Thread.currentThread().getName() + " second read x: " + currentX + "   y:  " + currentY);
                stampedLock.unlockRead(stamp);//释放悲观读锁
            }
        }
        System.out.println(Thread.currentThread().getName() + " last  X :  " + currentX + "  currentY :  " + currentY);
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}
